package pers.amos.eshop.service.impl;

import org.springframework.stereotype.Service;
import pers.amos.eshop.request.Request;
import pers.amos.eshop.request.RequestQueue;
import pers.amos.eshop.service.RequestAsyncProcessService;

import java.util.concurrent.ArrayBlockingQueue;

/**
 * @author amos wong
 * @create 2020-11-16 10:01 上午
 * <p>
 * 异步处理请求service的实现类
 */
@Service
public class RequestAsyncProcessServiceImpl implements RequestAsyncProcessService {

    @Override
    public void process(Request request) {
        try {
            // 1.做请求的路由，根据每个请求的商品id，路由到对应的内存队列中去
            ArrayBlockingQueue<Request> routingQueue = getRoutingQueue(request.getProductId());

            // 2.将请求放入该内存队列中，完成路由操作
            // 之所以放入阻塞队列中就是为了避免读写并发操作带来的安全问题
            routingQueue.put(request);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private ArrayBlockingQueue<Request> getRoutingQueue(Long productId) {
        RequestQueue requestQueue = RequestQueue.getInstance();

        // 先获取productId的hash值
        String key = String.valueOf(productId);
        int h;
        int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

        // 对hash值取模，将hash值路由到指定的内存队列中
        int index = (requestQueue.getQueueSize() - 1) & hash;

        System.out.println("===========日志===========: 路由内存队列，商品id=" + productId + ", 队列索引=" + index);

        return requestQueue.getQueue(index);
    }
}
